package com.example.app.service;

import com.example.app.entity.BodyEntry;
import com.example.app.entity.UserProfile;
import com.example.app.repository.BodyEntryRepository;
import com.example.app.repository.UserProfileRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import reactor.core.publisher.Mono;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class DeepSeekService{

    private final DeepSeekClient deepSeekClient;

    private final GradioClient gradioClient;
    @Autowired
    private BodyEntryRepository bodyEntryRepository;
    @Autowired
    private BodyEntryRepository ExerciseRepository;
    @Autowired
    private UserProfileRepository profileRepository;
    // Python 服务地址
    public DeepSeekService(DeepSeekClient deepSeekClient, GradioClient gradioClient) {
        this.deepSeekClient = deepSeekClient;
        this.gradioClient = gradioClient;
    }

    // 模拟检索方法 - 实际应替换为真实实现
    private List<Map<String, String>> retrieval(String message, int limit) {
        RestTemplate restTemplate = new RestTemplate();
        String url = "http://localhost:5000/retrieve";

        // 构建请求体
        Map<String, Object> request = Map.of(
                "query", message,
                "limit", limit
        );

        ResponseEntity<Map> response = restTemplate.postForEntity(
                url, request, Map.class // 改为接收Map而非List
        );

        // 步骤2：提取data字段并转换类型
        Map<String, Object> responseBody = response.getBody();
        List<Map<String, Object>> data = (List<Map<String, Object>>) responseBody.get("data");

        // 步骤3：将整型字段转为字符串
        List<Map<String, String>> result = new ArrayList<>();
        for (Map<String, Object> item : data) {
            Map<String, String> converted = new HashMap<>();
            converted.put("question_id", String.valueOf(item.get("question_id")));
            converted.put("ans_id", String.valueOf(item.get("ans_id")));
            converted.put("question", (String) item.get("question"));
            converted.put("answer", (String) item.get("answer"));
            converted.put("create_time", (String) item.get("create_time"));
            result.add(converted);
        }
        return result;
    }

    // 构建上下文
    private String buildContext(List<Map<String, String>> docs) {
        if (docs == null || docs.isEmpty()) {
            return "";
        }

        return docs.stream()
                .map(doc -> {
                    String question = doc.getOrDefault("question", "无问题内容");
                    String answer = doc.getOrDefault("answer", "无回答内容");
                    return String.format("【问题】%s\n【回答】%s\n---", question, answer);
                })
                .collect(Collectors.joining("\n"));
    }

    // 基础问答方法
    public Mono<String> answerQuestion(String message, boolean withRAG) {

        if (message == null || message.trim().isEmpty()) {
            return Mono.just("问题内容不能为空");
        }

        try {
            if (withRAG) {
                List<Map<String, String>> docs = retrieval(message, 5);
                String context = buildContext(docs);

                String prompt = context.isEmpty() ?
                        String.format("未找到相关文档，请直接回答：%s", message) :
                        String.format("参考以下问答对：\n%s\n\n请结合以上信息回答：%s", context, message);

                return deepSeekClient.getResponse(prompt);
            } else {
                return deepSeekClient.getResponse(message);
            }
        } catch (Exception e) {
            return Mono.just("处理问题时发生错误: " + e.getMessage());
        }
    }
    public Mono<String> answerQuestionLORA(String message, boolean withRAG) {

        if (message == null || message.trim().isEmpty()) {
            return Mono.just("问题内容不能为空");
        }

        try {
            if (withRAG) {
                List<Map<String, String>> docs = retrieval(message, 5);
                String context = buildContext(docs);

                String prompt = context.isEmpty() ?
                        String.format("未找到相关文档，请直接回答：%s", message) :
                        String.format("参考以下问答对：\n%s\n\n请结合以上信息回答：%s", context, message);

                return gradioClient.getResponse(prompt);
            } else {
                return gradioClient.getResponse(message);
            }
        } catch (Exception e) {
            return Mono.just("处理问题时发生错误: " + e.getMessage());
        }
    }
    // 带评估的问答方法
    public Mono<String> answerQuestionWithEvaluation(String message, String message2, boolean withRAG) {
        if (message == null || message.trim().isEmpty()) {
            return Mono.just("问题内容不能为空");
        }

        try {
            if (withRAG) {
                List<Map<String, String>> docs = retrieval(message, 3);
                String context = buildContext(docs);

                String prompt = context.isEmpty() ?
                        String.format("未找到相关文档，请直接回答：%s", message2) :
                        String.format("参考以下问答对：\n%s\n\n请结合以上信息回答：%s", context, message2);

                return deepSeekClient.getResponse(prompt);
            } else {
                return deepSeekClient.getResponse(message);
            }
        } catch (Exception e) {
            return Mono.just("处理问题时发生错误: " + e.getMessage());
        }
    }
    public String buildPrompt(Long userId, String message) {
        System.out.println(2);
        // 1. 获取最近 7 天的身体指标
        List<BodyEntry> entries = bodyEntryRepository
                .findTop7ByUserIdOrderByDateDesc(userId);
        System.out.println(3);
        // 2. 获取 profile 健康描述
        Optional<UserProfile> profileOpt = profileRepository.findByUserUserId(userId);
        System.out.println(profileOpt);
        String healthDesc = profileOpt.map(UserProfile::getHealthDescription)
                .orElse("暂无健康描述");

        // 3. 拼接身体指标文本
        StringBuilder metricsText = new StringBuilder("最近7天身体指标如下：\n");
        for (BodyEntry entry : entries) {
            metricsText.append(String.format("日期：%s，空腹血糖：%.1f，餐后血糖：%.1f，收缩压：%d，舒张压：%d，体重：%.1f\n",
                    entry.getDate(), entry.getFbg(), entry.getPbg(),
                    entry.getSbp(), entry.getDbp(), entry.getWeight()));
        }
        System.out.println(healthDesc);
        System.out.println(metricsText);
        // 4. 拼接完整 prompt
        return String.format(
                "用户健康描述：%s\n%s\n用户提问：%s",
                healthDesc, metricsText.toString(), message
        );
    }


    public String buildFoodPrompt(Long userId, String message) {
        List<BodyEntry> entries = ExerciseRepository
                .findTop7ByUserIdOrderByDateDesc(userId);

        Optional<UserProfile> profileOpt = profileRepository.findByUserUserId(userId);
        System.out.println(profileOpt);
        String healthDesc = profileOpt.map(UserProfile::getHealthDescription)
                .orElse("暂无健康描述");

        // 3. 拼接身体指标文本
        StringBuilder metricsText = new StringBuilder("最近7天身体指标如下：\n");
        for (BodyEntry entry : entries) {
            metricsText.append(String.format("日期：%s，空腹血糖：%.1f，餐后血糖：%.1f，收缩压：%d，舒张压：%d，体重：%.1f\n",
                    entry.getDate(), entry.getFbg(), entry.getPbg(),
                    entry.getSbp(), entry.getDbp(), entry.getWeight()));
        }
        System.out.println(healthDesc);
        System.out.println(metricsText);
        // 4. 拼接完整 prompt
        return String.format(
                "用户健康描述：%s\n%s\n食物信息：%s请根据上述健康情况为我推荐对于上述食物的饮食计划（是否该吃以及吃多少）",
                healthDesc, metricsText, message
        );
    }
    public String buildExercisePrompt(Long userId, String message) {
        List<BodyEntry> entries = bodyEntryRepository
                .findTop7ByUserIdOrderByDateDesc(userId);

        Optional<UserProfile> profileOpt = profileRepository.findByUserUserId(userId);
        System.out.println(profileOpt);
        String healthDesc = profileOpt.map(UserProfile::getHealthDescription)
                .orElse("暂无健康描述");

        // 3. 拼接身体指标文本
        StringBuilder metricsText = new StringBuilder("最近7天身体指标如下：\n");
        for (BodyEntry entry : entries) {
            metricsText.append(String.format("日期：%s，空腹血糖：%.1f，餐后血糖：%.1f，收缩压：%d，舒张压：%d，体重：%.1f\n",
                    entry.getDate(), entry.getFbg(), entry.getPbg(),
                    entry.getSbp(), entry.getDbp(), entry.getWeight()));
        }
        System.out.println(healthDesc);
        System.out.println(metricsText);
        // 4. 拼接完整 prompt
        return String.format(
                "用户健康描述：%s\n%s\n%s",
                healthDesc, metricsText, message
        );
    }
    public String buildMedicationPrompt(Long userId, String message) {
        List<BodyEntry> entries = bodyEntryRepository
                .findTop7ByUserIdOrderByDateDesc(userId);

        Optional<UserProfile> profileOpt = profileRepository.findByUserUserId(userId);
        System.out.println(profileOpt);
        String healthDesc = profileOpt.map(UserProfile::getHealthDescription)
                .orElse("暂无健康描述");

        // 3. 拼接身体指标文本
        StringBuilder metricsText = new StringBuilder("最近7天身体指标如下：\n");
        for (BodyEntry entry : entries) {
            metricsText.append(String.format("日期：%s，空腹血糖：%.1f，餐后血糖：%.1f，收缩压：%d，舒张压：%d，体重：%.1f\n",
                    entry.getDate(), entry.getFbg(), entry.getPbg(),
                    entry.getSbp(), entry.getDbp(), entry.getWeight()));
        }
        System.out.println(healthDesc);
        System.out.println(metricsText);
        // 4. 拼接完整 prompt
        return String.format(
                "用户健康描述：%s\n%s\n%s",
                healthDesc, metricsText, message
        );
    }
}